﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Web.Mvc;
using System.Web.WebPages;
using Fuse8.ContentManagementFramework.Web.Etc.PagePresent;
using Fuse8.DomainFramework.Common.Locator;

using Fuse8.ContentManagementFramework.Domain;
using Fuse8.ContentManagementFramework.SystemFacade;

namespace Fuse8.ContentManagementFramework.Web.MvcPowered
{
    public abstract class CmsWebViewPage<TModel> : WebViewPage<TModel>
    {
        private bool _isLoaded = false;

        protected Dictionary<string, IEnumerable<CmsPageControl>> _pageControls = new Dictionary<string, IEnumerable<CmsPageControl>>();

        public virtual CmsPage ContextPage
        {
            get
            {
                return DependencyServiceLocator.Current.GetInstance<ICmsContext>().ContextPage;
            }
        }
        
        internal Dictionary<string, IEnumerable<CmsPageControl>> PageControls
        {
            get
            {
                if (!_isLoaded)
                {
                    CmsPageInit();
                }

                return _pageControls;
            }
        }

        public HelperResult RenderRegion(string name)
        {
            return new HelperResult(
                p =>
                {
                    WriteControls(name, p)(p);
                });
        }

        public override void InitHelpers()
        {
            base.InitHelpers();

            CmsPageInit();
        }

        protected virtual void CmsPageInit()
        {
            var contextTemplate = TempData[CmsConfiguration.ContextTemplateKey] as CmsTemplate;

            if (contextTemplate != null)
            {
                //Template preview

                var contextTemplateRegions = contextTemplate.HasRegions ?
                contextTemplate.TemplateRegions :
                new List<CmsTemplateRegion>();

                //init page regions
                foreach (var templateRegion in contextTemplateRegions)
                {
                    if (!_pageControls.ContainsKey(templateRegion.TemplateRegionName))
                    {
                        _pageControls.Add(
                            templateRegion.TemplateRegionName,
                            new CmsPageControl[]
                        {
                            new CmsPageControl
                            {
                                PageControlTypeKey = (int)PageControlTypeKind.TemplateRegionPreview
                            }
                        });
                    }
                }

                //init page ViewBag, etc.
                ViewBag.PageName = string.Empty;
                ViewBag.Title = string.Format("{0} preview", contextTemplate.TemplateName);
                ViewBag.Description = string.Empty;
                ViewBag.Keywords = string.Empty;
            }
            else
            {
                //Front-end page

                var contextPage = ContextPage;

                if (contextPage != null)
                {
                    var contextPageTemplateRegions = contextPage.Template.HasRegions ?
                        contextPage.Template.TemplateRegions :
                        new List<CmsTemplateRegion>();

                    //init page regions
                    foreach (var templateRegion in contextPageTemplateRegions)
                    {
                        if (templateRegion.HasControls && !_pageControls.ContainsKey(templateRegion.TemplateRegionName))
                        {
                            _pageControls.Add(templateRegion.TemplateRegionName, templateRegion.RegionControls);
                        }
                    }

                    //init page ViewBag, etc.
                    var strategy = PagePresentStrategyFactory.GetStrategy(contextPage);
                    ViewBag.PageName = strategy.GetPageH1();
                    ViewBag.Title = strategy.GetPageMetaTitle();
                    ViewBag.Description = strategy.GetPageMetaDescription();
                    ViewBag.Keywords = strategy.GetPageMetaKeywords();
                }
            }

            _isLoaded = true;
        }

        protected virtual Action<TextWriter> WriteControls(string regionName, TextWriter writer)
        {
            return (p) =>
            {
                var controls = PageControls.ContainsKey(regionName) ?
                    PageControls[regionName] :
                    null;

                if (controls != null)
                {
                    foreach (var control in controls)
                    {
                        CmsMvcPageControlFactory.ExecuteControl(regionName, control, p, Html);
                    }
                }
            };
        }
    }
}
